import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

///布局约束练习
///布局约束思想：
///1、父Widget向子Widget传递约束条件
///2、子Widget向父Widget传递大小信息
///3、父Widget决定子Widget的位置
class ConstraintPage extends StatefulWidget {
  final List<Example> examples = [
    Example1(),
    Example2(),
    Example3(),
    Example4(),
    Example5(),
    Example6(),
    Example7(),
    Example8(),
    Example9(),
    Example10(),
    Example11(),
    Example12(),
    Example13(),
    Example14(),
    Example15(),
    Example16(),
    Example17(),
    Example18(),
  ];

  @override
  ConstraintPageState createState() => ConstraintPageState(examples);
}

class ConstraintPageState extends State<ConstraintPage> {
  int count;
  Widget example;
  String code;
  String explanation;
  final List<Example> examples;

  ConstraintPageState(this.examples);

  @override
  void initState() {
    count = 1;
    code = Example1().code;
    explanation = Example1().explanation;

    super.initState();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    var example = widget.examples[count - 1];
    code = example.code;
    explanation = example.explanation;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: '布局约束',
      home: Material(
        color: Colors.lightBlue,
        child: FittedBox(
          child: Container(
            width: 400,
            height: 600,
            child: Column(
              children: [
                Expanded(
                    child: ConstrainedBox(
                  constraints:
                      BoxConstraints.tightFor(width: double.infinity, height: double.infinity),
                  child: widget.examples[count - 1],
                )),
                Container(
                  height: 50,
                  width: double.infinity,
                  color: Colors.white,
                  child: SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    child: Row(
                      children: [
                        for (int i = 0; i < widget.examples.length; i++)
                          Container(
                            width: 58,
                            padding: EdgeInsets.only(left: 4, right: 4),
                            child: OutlinedButton(
                                onPressed: () {
                                  count = i + 1;
                                  setState(() {});
                                },
                                child: Text('${i + 1}')),
                          )
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

abstract class Example extends StatelessWidget {
  String get code;

  String get explanation;
}

class Example1 extends Example {
  final String code = 'Container(color: red)';
  final String explanation = 'The screen is the parent of the Container, '
      'and it forces the Container to be exactly the same size as the screen.'
      '\n\n'
      'So the Container fills the screen and paints it red.';

  @override
  Widget build(BuildContext context) {
    return Container(color: Colors.red);
  }
}

class Example2 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    return Center(child: Container(color: Colors.red, width: 100, height: 100));
  }
}

class Example3 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    return Align(
        alignment: Alignment.bottomRight,
        child: Container(color: Colors.red, width: 100, height: 100));
  }
}

class Example4 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    return Center(
        child: Container(color: Colors.red, width: double.infinity, height: double.infinity));
  }
}

class Example5 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///你可能会猜想 Container 的尺寸会在 70 到 150 像素之间，但并不是这样。 ConstrainedBox 仅对其从其父级接收到的约束下施加其他约束。
    ///在这里，屏幕迫使 ConstrainedBox 与屏幕大小完全相同，因此它告诉其子 Widget 也以屏幕大小作为约束，从而忽略了其 constraints 参数带来的影响。
    return ConstrainedBox(
        constraints: BoxConstraints(minWidth: 70, minHeight: 70, maxHeight: 150, maxWidth: 150),
        child: Container(color: Colors.red));
  }
}

class Example6 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///现在，Center 允许 ConstrainedBox 达到屏幕可允许的任意大小。 ConstrainedBox 将 constraints 参数带来的约束附加到其子对象上。
    /// Container 必须介于 70 到 150 像素之间。虽然它希望自己有 10 个像素大小，但最终获得了 70 个像素（最小为 70）。
    return Center(
      child: ConstrainedBox(
          constraints: BoxConstraints(minWidth: 70, minHeight: 70, maxHeight: 150, maxWidth: 150),
          child: Container(color: Colors.red, width: 10, height: 10)),
    );
  }
}

class Example7 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///现在，Center 允许 ConstrainedBox 达到屏幕可允许的任意大小。 ConstrainedBox 将 constraints 参数带来的约束附加到其子对象上。
    /// Container 必须介于 70 到 150 像素之间。虽然它希望自己有 1000 个像素大小，但最终获得了 150 个像素（最大为 150）。
    return Center(
      child: ConstrainedBox(
          constraints: BoxConstraints(minWidth: 70, minHeight: 70, maxHeight: 150, maxWidth: 150),
          child: Container(color: Colors.red, width: 1000, height: 1000)),
    );
  }
}

class Example8 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///屏幕强制 UnconstrainedBox 变得和屏幕一样大，而 UnconstrainedBox 允许其子级的 Container 可以变为任意大小。
    return UnconstrainedBox(child: Container(color: Colors.red, width: 20, height: 60));
  }
}

class Example9 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///屏幕强制 UnconstrainedBox 变得和屏幕一样大，而 UnconstrainedBox 允许其子级的 Container 可以变为任意大小。
    /// 不幸的是，在这种情况下，容器的宽度为 4000 像素，这实在是太大，以至于无法容纳在 UnconstrainedBox 中，
    /// 因此 UnconstrainedBox 将显示溢出警告（overflow warning）。
    return UnconstrainedBox(child: Container(color: Colors.red, width: 4000, height: 60));
  }
}

class Example10 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///屏幕强制 OverflowBox 变得和屏幕一样大，并且 OverflowBox 允许其子容器设置为任意大小。
    /// OverflowBox 与 UnconstrainedBox 类似，但不同的是，如果其子级超出该空间，它将不会显示任何警告。
    /// 在这种情况下，容器的宽度为 4000 像素，并且太大而无法容纳在 OverflowBox 中，但是 OverflowBox 会全部显示，而不会发出警告。
    return OverflowBox(
        maxWidth: double.infinity,
        minHeight: 0,
        maxHeight: double.infinity,
        minWidth: 0,
        child: Container(color: Colors.red, width: 4000, height: 60));
  }
}
class Example11 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///屏幕强制 FittedBox 变得和屏幕一样大，而 Text 则是有一个自然宽度（也被称作 intrinsic 宽度），它取决于文本数量，字体大小等因素。
    /// FittedBox 让 Text 可以变为任意大小。但是在 Text 告诉 FittedBox 其大小后， FittedBox 缩放文本直到填满所有可用宽度。
    return FittedBox(
      child: Text('Some Example Text.'),
    );
  }
}
class Example12 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///如果你将 FittedBox 放进 Center widget 中会发生什么？ Center 将会让 FittedBox 能够变为任意大小，取决于屏幕大小。
    ///FittedBox 然后会根据 Text 调整自己的大小，然后让 Text 可以变为所需的任意大小，由于二者具有同一大小，因此不会发生缩放。
    return Center(
      child: FittedBox(
        child: Text('Some Example Text.'),
      ),
    );
  }
}
class Example13 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///如果 FittedBox 位于 Center 中，但 Text 太大而超出屏幕，会发生什么？
    /// FittedBox 会尝试根据 Text 大小调整大小，但不能大于屏幕大小。然后假定屏幕大小，并调整 Text 的大小以使其也适合屏幕。
    return Center(
      child: FittedBox(
        child: Text(
            'This is some very very very large text that is too big to fit a regular screen in a single line.'),
      ),
    );
  }
}
class Example14 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///如果 FittedBox 位于 Center 中，但 Text 太大而超出屏幕，会发生什么？
    /// FittedBox 会尝试根据 Text 大小调整大小，但不能大于屏幕大小。然后假定屏幕大小，并调整 Text 的大小以使其也适合屏幕。
    return Center(
      child: Text(
          'This is some very very very large text that is too big to fit a regular screen in a single line.'),
    );
  }
}
class Example15 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///由于 Row 不会对其子级施加任何约束，因此它的 children 很有可能太大而超出 Row 的可用宽度。在这种情况下， Row 会和 UnconstrainedBox 一样显示溢出警告。
    return Row(
      children: [
        Container(
            color: Colors.red,
            child: Text('This is a very long text that won\'t fit the line.',
                style: TextStyle(fontSize: 24))),
        Container(color: Colors.green, child: Text('Goodbye!', style: TextStyle(fontSize: 24))),
      ],
    );
  }
}
class Example16 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///由于 Row 不会对其子级施加任何约束，因此它的 children 很有可能太大而超出 Row 的可用宽度。在这种情况下， Row 会和 UnconstrainedBox 一样显示溢出警告。
    return Row(
      children: [
        Expanded(
          flex: 2,
          child: Container(
            color: Colors.red,
            child: Text(
              'This is a very long text that won\'t fit the line.',
              style: TextStyle(fontSize: 24),
            ),
          ),
        ),
        Expanded(
          child: Container(
            color: Colors.green,
            child: Text(
              'Goodbye!',
              style: TextStyle(fontSize: 24),
            ),
          ),
        ),
      ],
    );
  }
}
class Example17 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///屏幕强制 Scaffold 变得和屏幕一样大，所以 Scaffold 充满屏幕。
    ///然后 Scaffold 告诉 Container 可以变为任意大小，但不能超出屏幕。
    return Scaffold(
      body: Container(
        color: Colors.blue,
        child: Column(
          children: [
            Text('Hello!'),
            Text('Goodbye!'),
          ],
        ),
      ),
    );
  }
}
class Example18 extends Example {
  final String code = '';
  final String explanation = '';

  @override
  Widget build(BuildContext context) {
    ///果你想要 Scaffold 的子级变得和 Scaffold 本身一样大的话，你可以将这个子级外包裹一个 SizedBox.expand。
    return Scaffold(
      body: SizedBox.expand(
        child: Container(
          color: Colors.blue,
          child: Column(
            children: [
              Text('Hello!'),
              Text('Goodbye!'),
            ],
          ),
        ),
      ),
    );
  }
}